import pickle
import socket
import threading
import struct
from time import time
import cv2
import time
import numpy as np
from core_algorithm import InterStatus

# 改成你自己的本机IP
host = "0.0.0.0"



def copy_bytes_arrays(dst, start, src):
    if start < 0:
        raise RuntimeError("start < 0")
    i = start
    for b in src:
        dst[i] = b
        i += 1


class TcpInput(threading.Thread):
    def __init__(self, port = 2333) -> None:
        super().__init__(daemon=False)
        self.buffer = None
        self.curr_id = None
        self.isQuit = False
        self.frame_buffer = None
        self.distan = None
        self.time_stamp = None
        self.address = '0.0.0.0'
        self.port = port
        self.frame_buffer_lock = threading.Lock()
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.s.bind((host, self.port))
        self.on_disconnect = None
        self.lastStatus = InterStatus()
        self.carStatus = InterStatus()

        
        self._on_connect_cb = None

    def on_connect(self, addr):
        if self._on_connect_cb is not None:
            print(f'calling cb ...')
            self._on_connect_cb(addr)

    def run(self):
        self.s.listen()
        print("wating for client")
        conn, addr = self.s.accept()
        print("accepted")
        self.address = addr[0]
        self.on_connect(self.address)
        self.carStatus.address = self.address
        while not self.isQuit:
            time_stamp = 0
            try:
                head = conn.recv(24)
            except socket.timeout as _:
                break
            try:
                packet_id, total_size, offset, dataLength, self.distan, time_stamp = struct.unpack("<iiiiii", head)
            except struct.error as _:
                break
            if self.curr_id is None:
                self.curr_id = packet_id
                self.buffer = bytearray(total_size)
            elif packet_id != self.curr_id:
                image = np.asarray(self.buffer, dtype="uint8")
                try:
                    image = cv2.imdecode(image, cv2.IMREAD_COLOR)
                    self.frame_buffer = image
                except cv2.error as _:
                    pass
                self.curr_id = packet_id
                self.buffer = bytearray(total_size)
            bias = 0
            while dataLength > 0:
                temp = conn.recv(dataLength)
                copy_bytes_arrays(self.buffer, bias, temp)
                dataLength -= len(temp)
                bias += len(temp)
            conn.sendall(struct.pack("<ii", packet_id, time_stamp))


    def retrieve(self):
        ret = None
        ret = self.frame_buffer, self.distan, self.time_stamp
        if self.frame_buffer is None:
            return None
        else:
            return ret

    def set_quit(self):
        self.isQuit = True
